package com.cy.stone.system.application.impl;

import com.cy.stone.common.errorcode.SysErrorCode;
import com.cy.stone.system.application.DictDataApi;
import com.cy.stone.system.domain.clientobject.dict.DictDataCO;
import com.cy.stone.system.domain.clientobject.dict.DictDataPageCO;
import com.cy.stone.system.domain.dto.dict.DictDataDTO;
import com.cy.stone.system.infrastructure.database.entity.DictDataEntity;
import com.cy.stone.system.infrastructure.database.entity.DictTypeEntity;
import com.cy.stone.system.infrastructure.database.service.IDictDataService;
import com.cy.stone.system.infrastructure.database.service.IDictTypeService;
import com.feiniaojin.gracefulresponse.GracefulResponseException;
import com.houkunlin.system.dict.starter.bean.DictValueVo;
import com.houkunlin.system.dict.starter.notice.RefreshDictValueEvent;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.Optional;

import static com.cy.stone.system.infrastructure.database.table.DictDataTableDef.DICT_DATA_ENTITY;
import static com.cy.stone.system.infrastructure.database.table.DictTypeTableDef.DICT_TYPE_ENTITY;

/**
 * 字典数据接口实现
 * @author Wings
 * @since 2023-12-18
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class DictDataApiImpl implements DictDataApi {

    private final IDictTypeService dictTypeService;

    private final IDictDataService dictDataService;

    private final ApplicationEventPublisher applicationEventPublisher;
    @Override
    public Page<DictDataDTO> page(DictDataPageCO dictDataPageCO) {
        Page<DictDataDTO> page = Page.of(dictDataPageCO.getPageNum(), dictDataPageCO.getPageSize());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select(
                        DICT_DATA_ENTITY.ID,
                        DICT_DATA_ENTITY.DICT_TYPE,
                        DICT_TYPE_ENTITY.DICT_NAME,
                        DICT_DATA_ENTITY.DICT_CODE,
                        DICT_DATA_ENTITY.DICT_VALUE,
                        DICT_DATA_ENTITY.DICT_SORT).from(DICT_TYPE_ENTITY.as("a"), DICT_DATA_ENTITY.as("b"))
                .where(DICT_TYPE_ENTITY.DICT_TYPE.eq(DICT_DATA_ENTITY.DICT_TYPE))
                .and(DICT_DATA_ENTITY.DICT_TYPE.eq(dictDataPageCO.getDictType()))
                .orderBy(DICT_DATA_ENTITY.DICT_TYPE, Boolean.TRUE)
                .orderBy(DICT_DATA_ENTITY.DICT_SORT, Boolean.TRUE);
        return dictDataService.pageAs(page, queryWrapper, DictDataDTO.class);
    }

    @Override
    public void addDictData(DictDataCO dictDataCO) {
        // 校验字典类型是否存在
        Optional<DictTypeEntity> dictType = dictTypeService.getOneOpt(QueryWrapper.create()
                .from(DICT_TYPE_ENTITY)
                .where(DICT_TYPE_ENTITY.DICT_TYPE.eq(dictDataCO.getDictType())));
        if (dictType.isPresent()) {
            // 校验字典数据是否已经存在
            Optional<DictDataEntity> dictData = dictDataService.getOneOpt(QueryWrapper.create()
                    .from(DICT_DATA_ENTITY)
                    .where(DICT_DATA_ENTITY.DICT_TYPE.eq(dictDataCO.getDictType()))
                    .and(DICT_DATA_ENTITY.DICT_CODE.eq(dictDataCO.getDictCode())));
            if (dictData.isPresent()) {
                log.error(dictDataCO.getDictType() + "-" + dictDataCO.getDictType() + "字典数据已经存在");
                throw new GracefulResponseException(SysErrorCode.DICT_DATA_EXIST.getCode(), SysErrorCode.DICT_DATA_EXIST.getMessage());
            } else {
                DictDataEntity dictDataEntity = DictDataCO.toAddEntity(dictDataCO);
                dictDataService.save(dictDataEntity);
                // 刷新字典缓存
                DictValueVo value = new DictValueVo(dictDataEntity.getDictType(), dictDataEntity.getDictCode(), dictDataEntity.getDictValue(), dictDataEntity.getDictSort());
                applicationEventPublisher.publishEvent(new RefreshDictValueEvent(value, Boolean.TRUE));
            }
        } else {
            log.error(dictDataCO.getDictType() + "字典类型不存在");
            throw new GracefulResponseException(SysErrorCode.DICT_TYPE_NOT_EXIST.getCode(), SysErrorCode.DICT_TYPE_NOT_EXIST.getMessage());
        }
    }

    @Override
    public void editDictData(DictDataCO dictDataCO) {
        // 校验字典类型是否存在
        Optional<DictTypeEntity> dictType = dictTypeService.getOneOpt(QueryWrapper.create()
                .from(DICT_TYPE_ENTITY)
                .where(DICT_TYPE_ENTITY.DICT_TYPE.eq(dictDataCO.getDictType())));
        if (dictType.isPresent()) {
            // 校验字典数据是否已经存在
            Optional<DictDataEntity> dictData = dictDataService.getByIdOpt(dictDataCO.getId());
            if (dictData.isPresent()) {
                DictDataEntity dictDataEntity = dictData.get();
                DictDataCO.toEditEntity(dictDataEntity, dictDataCO);
                dictDataService.updateById(dictDataEntity);
                // 刷新字典缓存
                DictValueVo value = new DictValueVo(dictDataEntity.getDictType(), dictDataEntity.getDictCode(), dictDataEntity.getDictValue(), dictDataEntity.getDictSort());
                applicationEventPublisher.publishEvent(new RefreshDictValueEvent(value, Boolean.TRUE));
            } else {
                log.error(dictDataCO.getDictType() + "-" + dictDataCO.getDictType() + "字典数据不存在");
                throw new GracefulResponseException(SysErrorCode.DICT_DATA_NOT_EXIST.getCode(), SysErrorCode.DICT_DATA_NOT_EXIST.getMessage());
            }
        } else {
            log.error(dictDataCO.getDictType() + "字典类型不存在");
            throw new GracefulResponseException(SysErrorCode.DICT_TYPE_NOT_EXIST.getCode(), SysErrorCode.DICT_TYPE_NOT_EXIST.getMessage());
        }
    }
}
